#include <stdio.h>
#include <string.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include "head.h"
#include <mysql/mysql.h>

// 加上文件下载判断,下载失败删除.更改打开文件的路径
int get_client(int netfd, char* token, user_t* user, char *path) {
    // 这里send filename,同时发送文件偏移量
    // 然后接受服务器返回的文件长,文件本体
    
    off_t token_len = strlen(token);
    send(netfd, &token_len, sizeof(off_t), MSG_NOSIGNAL);
    send(netfd, token, token_len, MSG_NOSIGNAL);
//    printf("token: %s\n", token);


    char name[32] = {0};
    strcpy(name, path);
    ssize_t lseek_offset = 0;


    char p_path[1024] = {0};
    memset(p_path, 0, sizeof(p_path));
    strcpy(p_path, user->path);
//printf("p_path: %s\n", p_path);
    off_t len = strlen(p_path);
    send(netfd, &len, sizeof(off_t), MSG_NOSIGNAL);
    send(netfd, p_path, len, MSG_NOSIGNAL);

    // 判断文件是否存在 ,如果不存在就正常下载文件,存在则截断下载
    
//    printf("--------------------------\n");
    int filefd;
    if ((filefd = open(path, O_RDWR | O_APPEND)) != -1) {
        // 文件已经存在,需要追加内容进去
        // 先写有文件的部分->传一个名字+偏移量的数据过去
        char sent[32 + sizeof(ssize_t)] = {0};
        ssize_t lseek_offset = 0;

        struct stat file;
        fstat(filefd, &file);
        lseek_offset = file.st_size;

        memcpy(sent, name, sizeof(name));
        memcpy(sent + 32, &lseek_offset, sizeof(ssize_t));
		//发送文件名和偏移量
        send(netfd, sent, sizeof(sent), 0);

        //如果server传一个'0'过来,表示没有这个文件
        char sig;
        recv(netfd, &sig, 1, 0);
        if (sig=='0')
        {
            printf("\n当前路径没有该文件\n");
            remove(name);
            return 0;
        }

        ssize_t flen = 0;
		char sha[41] = {0};
		char md[33] = {0};
		char *_info = (char*)calloc(sizeof(ssize_t) + 41 + 33, sizeof(char));
        recv(netfd, _info, sizeof(ssize_t) + 41 + 33, 0);
        memcpy(&flen, _info, sizeof(ssize_t));
        memcpy(sha, _info + sizeof(ssize_t), sizeof(sha));
		memcpy(md, _info + sizeof(ssize_t) + sizeof(sha), sizeof(md));
//		printf("接收到的文件哈希值:\n sha1 = %s\nmd5 = %s\n", sha, md);
		
		char *buffer = (char *)calloc(flen, sizeof(char));
		if (buffer == NULL) {
            perror("calloc");
            close(filefd);
            return -1;
        }
        ssize_t recvlen = 0;
        ssize_t ret_recv = 0;
        while (recvlen < flen) {
            ret_recv = recv(netfd, buffer + recvlen, flen - recvlen, 0);
            if (ret_recv == -1) {
                perror("recv");
                free(buffer);
                close(filefd);
                return -1;
            }
            recvlen += ret_recv;
        }
        if (write(filefd, buffer, flen) != flen) {
            perror("write");
            free(buffer);
            close(filefd);
            return -1;
        }
		//文件传输完毕,计算接收到文件的哈希值,与传送的哈希值作比较
        char sha1[41] = {0};
        char md1[33] = {0};
        char namepath[1024] = {0};

        memcpy(namepath, "sha1sum ", 8);
        memcpy(namepath + 8, name, sizeof(name));
        FILE *fp = popen(namepath, "r"); // -->计算哈希值,然后读取此处是sha1的
        fread(sha1, sizeof(char), sizeof(sha1) - 1, fp); // sha1哈希读取完毕
        sha1[40] = 0;
        memset(namepath, 0, sizeof(namepath)); // 清空路径;
        pclose(fp);                            // 关闭管道
        memcpy(namepath, "md5sum ", 7);
        memcpy(namepath + 7, name, sizeof(name));
        fp = popen(namepath, "r");
        fread(md1, sizeof(char), sizeof(md) - 1, fp);
        md1[32] = 0; // 强制将第33位修改为\0
//        printf("本地文件哈希值是\nsha1 = %s \nmd5 = %s \n", sha1, md1);
/*判断哈希值,下载失败则删除文件*/
        if((memcmp(sha, sha1, 41)==0)&&(memcmp(md, md1, 33)==0)){
            printf("\n文件接收完毕\n");
        }else{
            printf("\n文件接收失败\n");
            remove(name);
        }
        free(buffer);
        free(_info);
	} else {
//        printf("=====================================\n");
		// 没有文件,创建文件
        filefd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);

        char sent[32 + sizeof(ssize_t)] = {0};
        memcpy(sent, name, sizeof(name));

        send(netfd, sent, sizeof(sent), 0);
        // 也把偏移量发送过去,不过是0
        char sig;
        recv(netfd, &sig, 1, 0);
        if (sig == '0') {
            printf("\n当前路径没有该文件\n");
            remove(name);
            return 0;
        }
                //TODO
        //int a[2] = {1, 2,hello}; // 报错专用,修改接收到的长度,还有两个哈希值,顺序是41+33
        // 这里需要修改,附加接受server传过来的两个哈希值
        ssize_t flen = 0;
        char sha[41] = {0};
        char md[33] = {0};
        char *_info = (char*)calloc(sizeof(ssize_t) + 41 + 33, sizeof(char));
        recv(netfd, _info, sizeof(ssize_t) + 41 + 33, MSG_WAITALL);
        memcpy(&flen, _info, sizeof(ssize_t));
        memcpy(sha, _info + sizeof(ssize_t), sizeof(sha));
        memcpy(md, _info + sizeof(ssize_t) + sizeof(sha), sizeof(md));
//        printf("接收到的文件哈希值:\n sha1 = %s\nmd5 = %s\n", sha, md);

        // 接收一个文件长度,用于后面的truncate

        char *buffer = (char *)calloc(flen, sizeof(char));
        if (buffer == NULL) {
            perror("calloc");
            close(filefd);
            return -1;
        }
        ssize_t recvlen = 0;
        ssize_t ret_recv = 0;
        while (recvlen < flen) {
            ret_recv = recv(netfd, buffer + recvlen, flen - recvlen, 0);
            if (ret_recv == -1) {
                perror("recv");
                free(buffer);
                close(filefd);
                return -1;
            }
            recvlen += ret_recv;
        }
        if (write(filefd, buffer, flen) != flen) {
            perror("write");
            free(buffer);
            close(filefd);
            return -1;
        }
		// 文件传输完毕,计算接收到文件的哈希值,与传送的哈希值作比较
		char sha1[41] = {0};
		char md1[33] = {0};
		char namepath[1024] = {0};

		memcpy(namepath, "sha1sum ", 8);
        memcpy(namepath + 8, name, sizeof(name));
        FILE *fp = popen(namepath, "r");				  // -->计算哈希值,然后读取此处是sha1的
		fread(sha1, sizeof(char), sizeof(sha1) - 1,fp); // sha1哈希读取完毕
        sha1[40] = 0;
        memset(namepath, 0, sizeof(namepath));         // 清空路径;
        pclose(fp);                            // 关闭管道
        memcpy(namepath, "md5sum ", 7);
        memcpy(namepath + 7, name, sizeof(name));
        fp = popen(namepath, "r");
        fread(md1, sizeof(char), sizeof(md) - 1, fp);
        md1[32] = 0;                // 强制将第33位修改为\0
//        printf("本地文件哈希值是\nsha1 = %s \nmd5 = %s \n", sha1, md1);
        if ((memcmp(sha, sha1, 41) == 0) && (memcmp(md, md1, 33) == 0)) {
            printf("\n文件接收完毕\n");
        } else {
            printf("\n文件接收失败\n");
            remove(name);
        }
                free(buffer);
		free(_info);
    }
	close(filefd);
    return 0;
}
